package com.carr.service.impl;

import com.carr.api.dto.ActHistoryTaskDto;
import com.carr.api.dto.ActLinkUpSerchItemsDto;
import com.carr.api.dto.ActLinkUpTaskCreateDto;
import com.carr.api.entity.ActHistoryTaskEntity;
import com.carr.common.constant.TaskConstant;
import com.carr.common.exception.ActException;
import com.carr.common.response.HttpResponse;
import com.carr.common.response.HttpResponseUtil;
import com.carr.common.util.CommonUtil;
import com.carr.mapper.ActHistoryProcessInstanceMapper;
import com.carr.mapper.ActHistoryTaskMapper;
import com.carr.service.ActCommonService;
import com.carr.service.ActLinkUpService;
import com.carr.service.ActTaskService;
import org.activiti.engine.HistoryService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.history.HistoricTaskInstanceQuery;
import org.activiti.engine.impl.persistence.entity.TaskEntity;
import org.activiti.engine.task.Task;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.InvocationTargetException;
import java.util.*;

@Service
@Transactional
public class ActLinkUpServiceImpl implements ActLinkUpService {
    private final ActCommonService actCommonService;
    private final ActTaskService actTaskService;
    private final ActHistoryTaskMapper historyTaskMapper;
    private final TaskService taskService;
    private final ActHistoryProcessInstanceMapper historyProcessInstanceMapper;
    private final HistoryService historyService;

    public ActLinkUpServiceImpl(ActCommonService actCommonService, ActTaskService actTaskService, ActHistoryTaskMapper historyTaskMapper, TaskService taskService, ActHistoryProcessInstanceMapper historyProcessInstanceMapper, HistoryService historyService) {
        this.actCommonService = actCommonService;
        this.actTaskService = actTaskService;
        this.historyTaskMapper = historyTaskMapper;
        this.taskService = taskService;
        this.historyProcessInstanceMapper = historyProcessInstanceMapper;
        this.historyService = historyService;
    }

    @Override
    public HttpResponse getSearchItems() {
        ActLinkUpSerchItemsDto serchItemsVO = new ActLinkUpSerchItemsDto();
        List<String> instanceIds = historyProcessInstanceMapper.getInstanceIds();
        serchItemsVO.setInstanceIds(instanceIds);

        List<String> linkUpNames = historyTaskMapper.getLinkUpNames();
        serchItemsVO.setLinkUpNames(linkUpNames);

        return HttpResponseUtil.success("成功",serchItemsVO);
    }

    @Override
    public HttpResponse createLinkUpTask(ActLinkUpTaskCreateDto linkUpTaskCreateDto) {
        //流程结束抛出异常
        if (actCommonService.judgeProcessInstanceFinished(linkUpTaskCreateDto.getProcessInstanceId())) {
            throw new ActException("流程已经结束，不可发起沟通！");
        }

        //字段校验
        validataLinkUpTaskCreateDtoParams(linkUpTaskCreateDto);

        List<ActLinkUpTaskCreateDto.AssigneeWithPushMsg> assigneeWithPushMsgs = linkUpTaskCreateDto.getAssigneeWithPushMsgs();
        assigneeWithPushMsgs.forEach(assigneeWithPushMsg -> {
            TaskEntity taskEntity = new TaskEntity();
            taskEntity.setProcessDefinitionId(linkUpTaskCreateDto.getProcessDefinitionId());
            taskEntity.setProcessInstanceId(linkUpTaskCreateDto.getProcessInstanceId());
            //TODO owner应该为当前用户ID
            taskEntity.setOwner("currentUser");
            taskEntity.setAssignee(String.valueOf(assigneeWithPushMsg.getAssignee()));
            String id = UUID.randomUUID().toString();
            taskEntity.setId(id);
            taskEntity.setDescription(assigneeWithPushMsg.getDescription());
            taskEntity.setName(TaskConstant.TASK_LINK_UP_NAME);
            taskEntity.setTaskDefinitionKey(TaskConstant.TASK_CATE_LINK_UP);
            taskService.saveTask(taskEntity);
            //填充history字段
            ActHistoryTaskEntity historyTaskEntity = new ActHistoryTaskEntity();
            historyTaskEntity.setId(id);
            historyTaskEntity.setProcDefId(linkUpTaskCreateDto.getProcessDefinitionId());
            historyTaskEntity.setProcInstId(linkUpTaskCreateDto.getProcessInstanceId());
            historyTaskMapper.updateById(historyTaskEntity);
        });
        return HttpResponseUtil.success("沟通任务创建成功");
    }

    @Override
    public HttpResponse ack(String taskId, String assignee, String msg) {
        Task task = actTaskService.getTaskById(taskId);
        if (!assignee.equals(task.getAssignee())) {
            throw new RuntimeException("你不是该任务的承接人");
        }
        Map<String, Object> vars = new HashMap<>(1);
        vars.put("msg", msg);
        taskService.complete(taskId, vars);
        return HttpResponseUtil.success("回复消息成功");
    }

    @Override
    public HttpResponse deleteLinkupTask(String taskId, String owner) {
        Task task = actTaskService.getTaskById(taskId);
        if (!owner.equals(task.getOwner())) {
            throw new RuntimeException("不能取消他人的任务");
        }
        taskService.deleteTask(taskId, TaskConstant.DELETE_REASON_OWNER);
        return HttpResponseUtil.success("取消沟通任务成功");
    }

    @Override
    public Object getLinkupTaskList(String taskId, String processInstanceId, String owner, String deleteReason, int start, int length) {
        HistoricTaskInstanceQuery taskQuery = historyService.createHistoricTaskInstanceQuery();
        if (StringUtils.isNotEmpty(taskId)) {
            taskQuery.taskId(taskId);
        }
        if (StringUtils.isNotEmpty(processInstanceId)) {
            taskQuery.processInstanceId(processInstanceId);
        }
        if (StringUtils.isNotEmpty(owner)) {
            taskQuery.taskOwner(owner);
        }
        taskQuery.taskDefinitionKey(TaskConstant.TASK_CATE_LINK_UP);
        taskQuery.includeTaskLocalVariables();
        if (StringUtils.isNotEmpty(deleteReason)) {
            taskQuery.taskDeleteReason(deleteReason);
        }
        long count = taskQuery.count();
        taskQuery.orderByTaskCreateTime().desc();
        List<HistoricTaskInstance> queryList = taskQuery.listPage(start,length);
        List<ActHistoryTaskDto> list = new ArrayList<>(64);
        queryList.forEach(i -> {
            ActHistoryTaskDto taskVO = new ActHistoryTaskDto();
            try {
                BeanUtils.copyProperties(taskVO, i);
                Map<String, Object> localVariables = i.getTaskLocalVariables();
                Object msg = localVariables.get("msg");
                taskVO.setMsg(Objects.isNull(msg) ? "" : String.valueOf(msg));
                list.add(taskVO);
            } catch (IllegalAccessException | InvocationTargetException e) {
                e.printStackTrace();
            }
        });
        HashMap<String, Object> map = new HashMap<>();
        map.put("recordsTotal", count);
        map.put("recordsFiltered", count);
        map.put("data", list);
        return map;
    }

    /**
     * @description: 验证创建沟通接口参数
     * @author: yulin.chen
     * @date: 2020/9/24 10:11
     */
    private void validataLinkUpTaskCreateDtoParams(ActLinkUpTaskCreateDto linkUpTaskCreateDto) {
        CommonUtil.requireNonEmptyEntityProperties(linkUpTaskCreateDto);
    }
}
